#include "free_queue.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>

static int shm_fd;
static ShmLockFreeQueue* shm_queue;

bool shm_lock_free_queue_init(size_t buf_size) {
    // 创建共享内存
    shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666);
    if (shm_fd == -1) {
        perror("shm_open");
        return false;
    }

    // 设置共享内存大小
    size_t shm_size = sizeof(ShmLockFreeQueue) + QUEUE_SIZE * buf_size;
    if (ftruncate(shm_fd, shm_size) == -1) {
        perror("ftruncate");
        return false;
    }

    // 映射共享内存
    shm_queue = mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    if (shm_queue == MAP_FAILED) {
        perror("mmap");
        return false;
    }

    // 强制重置共享内存状态
    shm_queue->buf_size = buf_size;
    atomic_store(&shm_queue->head, 0);
    atomic_store(&shm_queue->tail, 0);
    atomic_store(&shm_queue->version, atomic_load(&shm_queue->version) + 1);  // 递增版本号

    return true;
}

bool shm_lock_free_queue_write(const char* data, size_t size) {
    if (size > shm_queue->buf_size) {
        fprintf(stderr, "Data size exceeds buffer size\n");
        return false;
    }

    int head, tail, next_tail;
    do {
        head = atomic_load(&shm_queue->head);
        tail = atomic_load(&shm_queue->tail);
        next_tail = (tail + 1) % QUEUE_SIZE;

        // 检查队列是否已满
        if (next_tail == head) {
            fprintf(stderr, "Queue is full\n");
            return false;
        }

        // 尝试更新 tail
    } while (!atomic_compare_exchange_weak(&shm_queue->tail, &tail, next_tail));

    // 写入数据
    memcpy(shm_queue->data[tail], data, size);

    // 确保写入操作完成
    atomic_thread_fence(memory_order_release);

    return true;
}

bool shm_lock_free_queue_read(char* data, size_t size) {
    if (size > shm_queue->buf_size) {
        fprintf(stderr, "Data size exceeds buffer size\n");
        return false;
    }

    static int local_version = -1;  // 消费者本地版本号
    //printf("local_version=%d,atomic_load(&shm_queue->version)=%d\n",local_version,atomic_load(&shm_queue->version));
    if (local_version != atomic_load(&shm_queue->version)) {
        // 版本号不匹配，重置消费者状态
	printf("reset head tail\n");
        local_version = atomic_load(&shm_queue->version);
        atomic_store(&shm_queue->head, atomic_load(&shm_queue->tail));  // 重置 head
    }

    int head, tail;
    do {
        head = atomic_load(&shm_queue->head);
        tail = atomic_load(&shm_queue->tail);

        // 检查队列是否为空
        if (head == tail) {
            fprintf(stderr, "Queue is empty\n");
            return false;
        }

        // 读取数据
        memcpy(data, shm_queue->data[head], size);

        // 尝试更新 head
    } while (!atomic_compare_exchange_weak(&shm_queue->head, &head, (head + 1) % QUEUE_SIZE));

    // 确保读取操作完成
    atomic_thread_fence(memory_order_acquire);

    return true;
}

void shm_lock_free_queue_destroy() {
    // 解除映射
    munmap(shm_queue, sizeof(ShmLockFreeQueue) + QUEUE_SIZE * shm_queue->buf_size);

    // 关闭共享内存
    close(shm_fd);
    shm_unlink(SHM_NAME);  // 销毁共享内存
}
